#ifndef Queue_CPP
#define Queue_CPP

#include<cstddef>

using namespace std;

template<class T>
class QueueNode
{
public:
    T* val;
    QueueNode* next;
};

template<class T>
class Queue
{
public:
    Queue();
    virtual ~Queue();
    Queue(const Queue& other);
    Queue& operator=(const Queue& other);
    T* dequeue ();
    void enqueue (T* node);
    QueueNode<T>* getHead();
    int hasElements();

private:
    QueueNode<T>* head;
    QueueNode<T>* tail;

};

template<class T>
int Queue<T>::hasElements()
{
    if (head != NULL)
    {
        return 1;
    }
    return 0;
}

template<class T>
Queue<T>::Queue()
{
    this->head = NULL;
    this->tail = NULL;
}

template<class T>
Queue<T>::~Queue()
{
    //dtor
}

template<class T>
Queue<T>::Queue(const Queue& other)
{
    //copy ctor
}

template<class T>
Queue<T>& Queue<T>::operator=(const Queue& rhs)
{
    if (this == &rhs) return *this; // handle self assignment
    //assignment operator
    return *this;
}

template<class T>
T* Queue<T>::dequeue ()
{
    if (head != NULL)
    {
        T* node;
        QueueNode<T>* temp = head;
        head = head->next;
        node = temp->val;
        temp->val = NULL;
        temp->next = NULL;
        delete(temp);
        if (head == NULL)
        {
            head = tail = NULL;
        }
        return node;
    }
    return NULL;
}

template<class T>
void Queue<T>::enqueue (T* node)
{
    QueueNode<T>* temp = new QueueNode<T>();
    temp->val = node;
    temp->next = NULL;
    if (tail == NULL)
    {
        head = tail = temp;
    }
    else
    {
        tail->next = temp;
        tail = tail->next;
    }
}

template<class T>
QueueNode<T>* Queue<T>::getHead()
{
    return this->head;
}

#endif
